package com.pactera.madp.cp.controller.sidebar.agent;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.pactera.madp.common.core.util.R;
import com.pactera.madp.common.security.annotation.Inner;
import com.pactera.madp.cp.api.dto.crm.CrmCustomQueryConditionDTO;
import com.pactera.madp.cp.api.entity.RadarContactEntity;
import com.pactera.madp.cp.api.entity.WorkContactEmployeeEntity;
import com.pactera.madp.cp.api.entity.WorkContactEntity;
import com.pactera.madp.cp.api.entity.crm.WorkCustomInfoEntity;
import com.pactera.madp.cp.api.entity.wx.WinXinEntity;
import com.pactera.madp.cp.common.util.ConnUtils;
import com.pactera.madp.cp.common.util.wx.Sha1Util;
import com.pactera.madp.cp.common.util.wx.WeiXinUtil;
import com.pactera.madp.cp.config.EsbSocketClientConfig;
import com.pactera.madp.cp.config.WxConfig;
import com.pactera.madp.cp.service.*;
import com.pactera.madp.cp.service.impl.EsbSocketService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Arrays;
import java.util.List;

/**
 * 微信服务
 */
@Slf4j
@Inner(value = false)
@RestController
@RequestMapping("/portal")
@AllArgsConstructor
@Api(value = "portal", tags = "微信服务管理")
public class WxPortalController {

    private WxConfig wxConfig;
    private EsbSocketService esbSocketService;
    private RadarContactService radarContactService;
    private WorkCustomInfoService workCustomInfoService;
    private IWorkContactEmployeeService contactEmployeeService;
    private IWorkContactService contactService;
    private static EsbSocketClientConfig esbSocketClientConfig;

    @Autowired
    public void setEsbSocketClientConfig(EsbSocketClientConfig esbSocketClientConfig) {
        WxPortalController.esbSocketClientConfig = esbSocketClientConfig;
    }

    /**
     * 微信接入校验处理
     *
     * @param appId     多公众号标志位
     * @param signature 微信签名
     * @param timestamp 时间戳
     * @param nonce     随机数
     * @param echostr   随机字符串
     * @return
     */
    @ApiOperation(value = "微信接入校验处理")
    @GetMapping(produces = "text/plain;charset=utf-8")
    public String authGet(@PathVariable("appId") String appId,
                          @RequestParam(name = "signature", required = false) String signature,
                          @RequestParam(name = "timestamp", required = false) String timestamp,
                          @RequestParam(name = "nonce", required = false) String nonce,
                          @RequestParam(name = "echostr", required = false) String echostr) {

        log.info("接收到来自微信服务器的认证消息：[{}, {}, {}, {}]", signature, timestamp, nonce, echostr);

        if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) {
            throw new IllegalArgumentException("请求参数非法，请核实!");
        }

        if (!wxConfig.getAppId().equals(appId)) {
            throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置，请核实！", appId));
        }

        if (checkSignature(timestamp, nonce, signature)) {
            return echostr;
        }

        return "非法请求";
    }


    /**
     * 获取微信签名
     * @param url 问号之后的内容需进行URL编码
     * @return
     */
    @PostMapping("/sign")
    @ApiOperation(value = "获取微信签名")
    public R getSign(String url) {
        try {
            // 从微信银行获取票据
            String respMsg = WeiXinUtil.doGet(wxConfig.getTicketUrl());
            log.info("获取票据：" + respMsg);
            JSONObject ticketJson = JSONUtil.parseObj(respMsg);
            WinXinEntity wx = WeiXinUtil.getWinXinEntity(url, ticketJson.getStr("jsapi_ticket"));
            wx.setAppId(ticketJson.getStr("appid"));
            return R.ok(wx);
        } catch (Exception e) {
            log.error("获取票据失败",e);
        }
        return R.failed();
    }

    /**
     * 获取微信签名
     * @return
     */
//    @PostMapping("/sign")
//    public WinXinEntity getSign(@PathVariable("appId") String appId, String url) {
//        if (!wxConfig.getAppId().equals(appId)) {
//            throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置，请核实！", appId));
//        }
//        return WeiXinUtil.getWinXinEntity(url, wxConfig.getAppId(), wxConfig.getAppSecret());
//    }

    private boolean checkSignature(String timestamp, String nonce, String signature) {
        //对四个参数做密文认证的处理将token、timestamp、nonce三个参数进行字典(数组)序排序
        String[] params = new String[]{wxConfig.getToken(), timestamp, nonce};
        //做字典排序
        Arrays.sort(params);

        //将三个参数字符串拼接成一个字符串进行sha1加密
        StringBuffer sb = new StringBuffer();
        for(String str:params){
            sb.append(str);
        }
        String content = sb.toString();
        //进行加密操作
        String secretContent = Sha1Util.sha1(content);

        //开发者获得加密后的字符串可与signature对比，标识该请求来源于微信
        if(!signature.equals(secretContent)){
            //认证失败
            throw new RuntimeException("认证失败！");
        }

        log.info("认证成功");
        return true;
    }

    /**
     * 获取微信用户openid
     * @return
     */
    @ApiOperation(value = "获取微信用户openid")
    @GetMapping("/wxUserOpenid")
    public R wxUserOpenid(String code, String openId) {
        RadarContactEntity radarContactEntity = null;
        Boolean exists = false;
        try {
            if (!(openId == null || "".equals(openId))) {
                radarContactEntity = radarContactService.getById(openId);
                if (radarContactEntity != null) {
                    exists = true;
//                    return R.ok(radarContactEntity);
                }
            }
            if (!exists) {
                if (code == null || "".equals(code)) {
                    return R.failed("请求失败：openId未匹配到实体，而code也为空");
                }
                // 从微信银行获取openid
//            String baseUrl = "http://6.32.6.46:7060/gateway/GetWXUserOpenId?_ChannleId=hrxjwxbank&code={}";
                String baseUrl = wxConfig.getWxUserOpenidUrl();
                String url = StrUtil.format(baseUrl, code);
                log.info("获取url：" + url);
                String respMsg = WeiXinUtil.doGet(url);
                log.info("获取openid：" + respMsg);
                JSONObject json = JSONUtil.parseObj(respMsg);
                String accessToken = json.getStr("access_token");
                openId = json.getStr("openid");
                radarContactEntity = radarContactService.getById(openId);
                if (radarContactEntity == null) {
                    synchronized (this) {
                        radarContactEntity = new RadarContactEntity();
                        radarContactEntity.setOpenId(openId);
                        // 新建客户 游客身份
                        radarContactEntity.setType("0");
                        radarContactService.save(radarContactEntity);
                    }
                }
                String userStr = WeiXinUtil.getWxinUserInfo(accessToken, openId);
                JSONObject jsonObject = JSONUtil.parseObj(userStr);
                String errorcode = jsonObject.getStr("errcode");
                if ("40003".equals(errorcode)) {
                    log.info("获取微信用户信息失败：" + userStr);
                    return R.failed("获取微信用户信息失败");
                }
                radarContactEntity = JSONUtil.toBean(userStr, RadarContactEntity.class);
                radarContactEntity.setOpenId(openId);
                log.info("企业微信获取用户信息：" + userStr);
            }

            String rsp = null;
            try {
                String req = esbSocketService.createReq(openId);
                String ip = esbSocketClientConfig.getHost();
                Integer port = esbSocketClientConfig.getPort();
                Integer timeout = esbSocketClientConfig.getReqTimeout();
                rsp = ConnUtils.connect(req, ip, port, timeout);
                log.info("esb响应报文:{}", rsp);
            } catch (Exception e) {
                log.info("esb请求失败:{}", e);
                e.printStackTrace();
            }
            String coreCstNo = null;
            if (rsp != null && !rsp.isEmpty()) {
                try {
                    coreCstNo = esbSocketService.getCoreCstNo(rsp);
                    log.info("解析esb响应报文，获取核心客户号:{}", coreCstNo);
                } catch (Exception e) {
                    log.error("esb响应报文中获取核心客户号失败");
                }
            }
            if (coreCstNo != null && !coreCstNo.isEmpty()) {
                // 获取到核心客户号 游客身份转为crm客户身份
                radarContactEntity.setType("2");
                radarContactEntity.setCustNo(coreCstNo);
                CrmCustomQueryConditionDTO dto = new CrmCustomQueryConditionDTO();
                dto.setCustNo(coreCstNo);
                dto.setDelFlag(0);
                List<WorkCustomInfoEntity> list = workCustomInfoService.listByCondition(dto);
                if (list != null && list.size() > 0) {
                    WorkCustomInfoEntity entity = list.get(0);
                    String mobileTel = entity.getMobileTel();
                    radarContactEntity.setMobileTel(mobileTel);
                    // 如果该crm客户类型为crm行内,判断该客户是否为行内客户
                    if (entity.getCustType() == 1) {
                        List<WorkContactEmployeeEntity> relations = contactEmployeeService.list(
                                Wrappers.<WorkContactEmployeeEntity>lambdaQuery()
                                        .like(WorkContactEmployeeEntity::getRemarkMobiles, mobileTel)
                        );
                        if (relations != null && relations.size() > 0) {
                            Integer contactId = relations.get(0).getContactId();
                            WorkContactEntity contact = contactService.getById(contactId);
                            if (contact != null) {
                                radarContactEntity.setContactId(contact.getId());
                                radarContactEntity.setWxExternalUserid(contact.getWxExternalUserid());
                                // 获取到crm客户信息 行内客户转为行内客户身份
                                radarContactEntity.setType("1");
                                radarContactEntity.setNickname(entity.getPecustName());
                                String sex = entity.getSex();
                                if ("20740001".equals(sex)) {
                                    radarContactEntity.setSex(1);
                                } else if ("20740002".equals(sex)) {
                                    radarContactEntity.setSex(2);
                                } else {
                                    radarContactEntity.setSex(0);
                                }
                            }
                        }
                    }
                }
            }
            radarContactService.updateById(radarContactEntity);
            log.info("请求调用完毕");
            log.info("响应实体:{}", radarContactEntity);
            return R.ok(radarContactEntity);
        } catch (Exception e) {
            log.error("获取客户信息失败", e);
        }
        return R.failed();
    }
}
